package sicnu.cs.ich.user.rest;

import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import sicnu.cs.ich.api.common.Constants;
import sicnu.cs.ich.api.common.ResultInfo;
import sicnu.cs.ich.api.domain.dto.CertificationDTO;
import sicnu.cs.ich.api.domain.entity.Certification;
import sicnu.cs.ich.api.domain.entity.UserInfo;
import sicnu.cs.ich.api.domain.form.*;
import sicnu.cs.ich.api.domain.vo.UserVo;
import sicnu.cs.ich.common.util.ResultInfoUtil;
import sicnu.cs.ich.security.domain.entity.Permission;
import sicnu.cs.ich.security.domain.entity.Role;
import sicnu.cs.ich.security.domain.entity.User;
import sicnu.cs.ich.security.service.IPermissionService;
import sicnu.cs.ich.security.service.IRoleService;
import sicnu.cs.ich.security.service.IUserService;
import sicnu.cs.ich.security.util.SecurityUtil;
import sicnu.cs.ich.user.service.*;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;
import static sicnu.cs.ich.security.util.SecurityUtil.getCurrentUserId;

/**
 * @author 沈洋 邮箱:1845973183@qq.com
 * @create 2021/10/20-14:35
 **/
@Slf4j
@RestController
@RequestMapping("/admin")
@RequiredArgsConstructor
@Api(tags = {"管理员模块"})
public class AdminResource {
    private final IPermissionService permissionService;
    private final IAdminService adminService;
    private final PasswordEncoder passwordEncoder;
    private final ICertService certService;
    private final IRoleService roleService;
    private final IUserService userService;
    @GetMapping("/menuTree")
    @ApiOperation("获取管理界面")
    public ResultInfo<List<Permission>> getMenuTree() {
        System.out.println(SecurityContextHolder.getContext().getAuthentication().getAuthorities());
        return ResultInfoUtil.buildSuccess(permissionService.getUserPermissionMenu(SecurityUtil.getCurrentUserId()));
    }
    @GetMapping("/role")
    @ApiOperation("完整的角色列表")
    public ResultInfo<List<Role>> getRoles(){
        var roles = roleService.getRoles();
        return ResultInfoUtil.buildSuccess(roles);
    }
    @PostMapping("/user")
    @ApiOperation("用户列表")
    public ResultInfo<PageInfo<UserVo>> allUser(@RequestBody PageParam param) {
        if ("".equals(param.getKey())) {
            param.setKey(null);
        }
        return ResultInfoUtil.buildSuccess(adminService.getUsers(param));
    }

    @PutMapping("/user/{userId}/role")
    @ApiOperation("修改用户角色")
    public ResultInfo<List<Role>> updateUserRole(@PathVariable Integer userId ,
                                           @Valid @RequestBody JsonArray roleIds){
        var updateRoleIds = Arrays.stream(roleIds.getArray()).collect(Collectors.toSet());
        // 将前端传入的数组进行去重并只保留合法的roleId
        var allRole = roleService.getRoles();
        var allRoleIds = allRole.stream().map(Role::getId)
                .collect(Collectors.toSet());
        var finalRoleId = updateRoleIds.stream().filter(allRoleIds::contains)
                .collect(Collectors.toSet());
        // 更新用户角色
        if (adminService.updateUserRole(userId,finalRoleId)) {
            var roles = roleService.getUserRole(userId);
            return ResultInfoUtil.buildSuccess(roles);
        }
        return ResultInfoUtil.buildError("修改失败");
    }
    @PutMapping("/user/password")
    @ApiOperation("重置密码")
    public ResultInfo<Void> resetUserPassword(@Valid @RequestBody JsonArray array) {
        boolean success = adminService.resetUserPassword(array.getArray()
                , passwordEncoder.encode(Constants.RESET_PASSWORD));
        if (success) {
            return ResultInfoUtil.buildSuccess("密码重置为："
                    + Constants.RESET_PASSWORD);
        } else {
            return ResultInfoUtil.buildError("密码重置失败，请重试");
        }
    }

    @GetMapping("/user/{userId}")
    @ApiOperation("用户信息")
    public ResultInfo<Map<String,Object>> getUserInfo(@PathVariable Integer userId){
        // 获取用户信息
        UserInfo userInfo = userService.findUserInfo(getCurrentUserId());
        User user = userService.findUser(getCurrentUserId());
        return ResultInfoUtil
                .buildSuccess(Map.of("user",user,"userInfo",userInfo));
    }
    @PutMapping("/user")
    @ApiOperation("创建新用户")
    public ResultInfo<Void> addUser(UserForm userForm){
        // 校验验证码是否存在或长度是否为6
        return userService.handleRegister(userForm);
    }

    @PutMapping("/user/lock/{userId}/{lockState}")
    @ApiOperation("修改用户账号状态")
    public ResultInfo<Integer> accountLock(@PathVariable Integer userId,@PathVariable Integer lockState) {
        if (lockState!=0&&lockState!=1){
            return ResultInfoUtil.buildError("参数错误");
        }
        if (adminService.updateUserState(userId,lockState)) {
            return ResultInfoUtil.buildSuccess("修改成功",lockState==1?0:1);
        }else return ResultInfoUtil.buildError("修改失败");
    }
    @ApiOperation("审核认证列表")
    @PostMapping("/cert")
    public ResultInfo<PageInfo<Certification>> getCert(@Valid @RequestBody CertParam param) {
        // modify_date升序 status升序
        if("".equals(param.getKey())){
            param.setKey(null);
        }
        PageInfo<Certification> list = certService.getCertList(param);
        return ResultInfoUtil.buildSuccess(list);
    }

    @ApiOperation("认证详情")
    @GetMapping("/cert/{certId}")
    public ResultInfo<CertificationDTO> getCertificationDTO(@PathVariable String certId) {
        var cert = certService.getCertDTO(certId);
        return cert == null ? ResultInfoUtil.buildError("无认证信息")
                : ResultInfoUtil.buildSuccess(cert);
    }

    @PostMapping("/role")
    @ApiOperation("角色列表")
    @PreAuthorize("hasAuthority('system:role')")
    public ResultInfo<PageInfo<Role>> getRoles(@RequestBody PageParam param){
        var roles = adminService.getRoles(param);
        return ResultInfoUtil.buildSuccess(roles);
    }
    @PreAuthorize("hasAuthority('system:role')")
    @ApiOperation("角色详情")
    @GetMapping("/role/{roleId}")
    public ResultInfo<Map<String,Object>> getRole(@PathVariable Integer roleId){
        // 获取角色信息
        var role = roleService.getRole(roleId);
        // 获取角色对应的权限信息
        var permissions =  permissionService.getRolePermission(List.of(role.getId()));
        return ResultInfoUtil.buildSuccess(
                Map.of("role",role,"permissions",permissions));
    }

    @ApiOperation("新增角色")
    @PutMapping("/role")
    @PreAuthorize("hasAuthority('system:role:add')")
    public ResultInfo<Void> addRole(@Valid @RequestBody RoleForm roleForm){
        // todo 前端传的权限ID有重复
        if (roleService.isRoleExisted(roleForm.getRole())) {
            return ResultInfoUtil.buildError("角色已存在");
        }
        return roleService.addRole(roleForm)?
                ResultInfoUtil.buildSuccess("新增成功"):ResultInfoUtil.buildError("新增失败");
    }
    @ApiOperation("删除角色")
    @DeleteMapping("/role/{roleId}")
    @PreAuthorize("hasAuthority('system:role:add')")
    public ResultInfo<Void> deleteRole(@PathVariable Integer roleId){
        // 删除角色(不能删除ROLE_ADMIN,ROLE_USER)
        var deleteRole = roleService.getRole(roleId);
        if (deleteRole!=null&&!"ROLE_ADMIN".equals(deleteRole.getRole())
                &&"ROLE_PERSON".equals(deleteRole.getRole())) {
            // 删除角色
            if (roleService.deleteRole(roleId)) {
                return ResultInfoUtil.buildSuccess("操作成功");
            }
        }
        return ResultInfoUtil.buildError("操作失败");
    }

    @ApiOperation("完整的权限树")
    @GetMapping("/permission")
    public ResultInfo<List<Permission>> permission(){
        return ResultInfoUtil.buildSuccess(permissionService.getPermissions());
    }


    @PutMapping("/cert/{certId}/{isConfirm}")
    @ApiOperation("确认认证/驳回认证")
    public ResultInfo<Void> certUser(@PathVariable String certId,@PathVariable Integer isConfirm) {
        // 确实失败是将文件和姓名重置
        // 校验参数合法性
        if (isConfirm!=-1&&isConfirm!=1){
            return ResultInfoUtil.buildError("参数错误");
        }
        // 验证认证信息是否存在
        Certification certification = certService.getCert(certId);
        if (certification==null){
            return ResultInfoUtil.buildError("无认证信息");
        }
        // 校验是否重复操作
        int curState = certification.getStatus();
        if (curState == isConfirm){
            return ResultInfoUtil.buildError("重复操作");
        }
        boolean success = false;
        // 判断是确认认证还是驳回认证
        switch (isConfirm){
            // 确认认证
            case 1: {
                success = certService.confirmCertification(certification);
                break;
            }
            // 驳回认证
            case -1:{
                success = certService.refuseCertification(certification);
                break;
            }
        }
        return success?ResultInfoUtil.buildSuccess("操作成功")
                :ResultInfoUtil.buildError("操作失败");
    }


}
